import type {CookieOptions, NuxtApp} from "#app";
import { getCookie, setCookie } from 'h3'
import { parse, serialize } from 'cookie-es'
import { destr } from 'destr'
import { isNil } from 'ramda'

interface _CookieOptions extends CookieOptions {
    nuxtApp?: NuxtApp
}

export class Cookie {
    static #defuOpts: _CookieOptions = {
        path: '/',
        watch: true,
        decode: val => destr(decodeURIComponent(val)),
        encode: val => encodeURIComponent(typeof val === 'string' ? val : JSON.stringify(val))
    }

    public static get(name: string, opts: _CookieOptions = {}) {
        const _opts = { ...Cookie.#defuOpts, ...opts }
        if (import.meta.server) {
            const nuxtApp = _opts?.nuxtApp ?? getNuxtApp()
            const event = nuxtApp?.ssrContext?.event
            if (isNil(event)) return
            return getCookie(event, name)
        } else {
            const cookies = parse(document.cookie, _opts)
            return cookies[name]
        }
    }
    public static set(name: string, value: any, opts: _CookieOptions = {}) {
        const _opts = { ...Cookie.#defuOpts, ...opts }
        if (import.meta.server) {
            const nuxtApp = opts?.nuxtApp ?? getNuxtApp()
            const event = nuxtApp?.ssrContext?.event
            if (isNil(event)) return
            setCookie(event, name, value, _opts)
        } else {
            let rawCookies: string
            if (value === null || value === undefined) {
                rawCookies = serialize(name, value, { ..._opts, maxAge: -1 })
            } else {
                rawCookies =  serialize(name, value, _opts)
            }
            document.cookie = rawCookies ?? document.cookie
        }
        return value
    }
}
